#pragma once
#include"log.hpp"
#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cstring>
#define pathname "/home/drw1/linux/testSHARE/process.hpp"
#define PROJ_ID 0x8888 
#define SIZE 4096 //一个段大小 
#define MODE 0666 //权限设置
#define PIPE_NAME "./myfifo"
#define NUM 1024
#define processnum 5

enum Status
{
    FIFO_CREATE_ERR,
    FIFO_OPEN_ERR,
    FIFO_READ_ERR,
    FIFO_CLOSE_ERR,
    FIFO_UNLINK_ERR,
    FORK_ERR
};
//建议SIZE的大小为4096的整数倍，以防止空间浪费
LOG log(PRINT_TO_SCREEN);


class Pipe
{
public:
    Pipe()
    {
        int n=mkfifo(PIPE_NAME, MODE);
        if(n)
        {
            perror("mkfifo failed");
            exit(FIFO_CREATE_ERR);
        }
    }

    static void open_pipes(int& fd)
    {
        fd=open(PIPE_NAME, O_RDONLY);
        if(fd<0)
        {
            perror("open failed");
            exit(FIFO_OPEN_ERR);
        }
    }

    static void open_pipec(int& fd)
    {
        fd=open(PIPE_NAME, O_WRONLY);
        if(fd<0)
        {
            perror("open failed");
            exit(FIFO_OPEN_ERR);
        }
    }

    static void write_pipe(int& fd)
    {
        string str;
        while(1)
        {
            cout<<"this is client: Your input: ";
            getline(cin,str);
            write(fd,str.c_str(), str.size());
            sleep(1);
        }
    }
    static void read_pipe(int& fd)
    {
        char PIPE_BUF[NUM];
        while(1)
        {
            memset(PIPE_BUF, 0, sizeof(PIPE_BUF));
            ssize_t n=read(fd, PIPE_BUF, sizeof(PIPE_BUF));
            if(n>0)
            {
                cout<<"server read data: "<<PIPE_BUF<<endl;
            }
            else if(n==0) break;
            else
            {
                perror("read failed");
                exit(FIFO_READ_ERR);
            }
        }
    }

    static void close_pipe(int& fd)
    {
        int n=close(fd);
        if(n<0)
        {
            perror("close failed");
            exit(FIFO_CLOSE_ERR);
        }
    }

    ~Pipe()
    {
        int n=unlink(PIPE_NAME);
        if(n<0)
        {
            perror("unlink failed");
            exit(FIFO_UNLINK_ERR);
        }
    }

};

key_t GetKey()
{
    key_t key = ftok(pathname, PROJ_ID);
    if(key==-1)
    {
        log(FATAL, "GetKey failed: %s", strerror(errno));
        exit(1);
    }
    log(INFO, "GetKey success");
    return key;
}

int CreateMemory()
{
    int shmid=shmget(GetKey(), SIZE, IPC_CREAT | IPC_EXCL | MODE);
    if(shmid==-1)
    {
        log(FATAL, "GetMemory failed: %s", strerror(errno));
        exit(2);
    }
    log(INFO, "GetMemory success");
    return shmid;
}

int GetMemory()
{
    return shmget(GetKey(), SIZE, IPC_CREAT | MODE);
}